home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / access / index / genam.c next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  9.2 KB  |  345 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *     genam.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    general index access method routines
  7.  *
  8.  *   INTERFACE ROUTINES
  9.  *
  10.  *   NOTES
  11.  *    many of the old access method routines have been turned into
  12.  *    macros and moved to genam.h -cim 4/30/91
  13.  *
  14.  * old comments:
  15.  * Scans are implemented as follows:
  16.  *
  17.  * `0' represents an invalid item pointer.
  18.  * `-' represents an unknown item pointer.
  19.  * `X' represents a known item pointers.
  20.  * `+' represents known or invalid item pointers.
  21.  * `*' represents any item pointers.
  22.  *
  23.  * State is represented by a triple of these symbols in the order of
  24.  * previous, current, next.  Note that the case of reverse scans works
  25.  * identically.
  26.  *
  27.  *    State    Result
  28.  * (1)    + + -    + 0 0        (if the next item pointer is invalid)
  29.  * (2)        + X -        (otherwise)
  30.  * (3)    * 0 0    * 0 0        (no change)
  31.  * (4)    + X 0    X 0 0        (shift)
  32.  * (5)    * + X    + X -        (shift, add unknown)
  33.  *
  34.  * All other states cannot occur.
  35.  *
  36.  * Note:
  37.  *    It would be possible to cache the status of the previous and
  38.  *    next item pointer using the flags.
  39.  * ----------------------------------------------------------------
  40.  */
  41.  
  42. #include "tmp/postgres.h"
  43.  
  44. #include "access/attnum.h"
  45. #include "access/genam.h"
  46. #include "access/heapam.h"
  47. #include "access/itup.h"
  48. #include "access/newam.h"
  49. #include "access/relscan.h"
  50. #include "access/sdir.h"
  51. #include "access/skey.h"
  52.  
  53. #include "storage/form.h"
  54. #include "utils/log.h"
  55. #include "utils/rel.h"
  56.  
  57. #include "catalog/catname.h"
  58. #include "catalog/pg_attribute.h"
  59. #include "catalog/pg_index.h"
  60. #include "catalog/pg_proc.h"
  61.  
  62. RcsId("$Header: /private/postgres/src/access/index/RCS/genam.c,v 1.8 1992/03/06 00:17:12 mer Exp $");
  63.  
  64. /* ----------------------------------------------------------------
  65.  *    general access method routines
  66.  *
  67.  *    All indexed access methods use an identical scan structure.
  68.  *    We don't know how the various AMs do locking, however, so we don't
  69.  *    do anything about that here.
  70.  *
  71.  *    The intent is that an AM implementor will define a front-end routine
  72.  *    that calls this one, to fill in the scan, and then does whatever kind
  73.  *    of locking he wants.
  74.  * ----------------------------------------------------------------
  75.  */
  76.  
  77. /* ----------------
  78.  *  RelationGetIndexScan -- Create and fill an IndexScanDesc.
  79.  *
  80.  *    This routine creates an index scan structure and sets its contents
  81.  *    up correctly. This routine calls AMrescan to set up the scan with
  82.  *    the passed key.
  83.  *
  84.  *    Parameters:
  85.  *        relation -- index relation for scan.
  86.  *        scanFromEnd -- if true, begin scan at one of the index's
  87.  *                   endpoints.
  88.  *        numberOfKeys -- count of scan keys (more than one won't
  89.  *                necessarily do anything useful, yet).
  90.  *        key -- the ScanKey for the starting position of the scan.
  91.  *
  92.  *    Returns:
  93.  *        An initialized IndexScanDesc.
  94.  *
  95.  *    Side Effects:
  96.  *        Bumps the ref count on the relation to keep it in the cache.
  97.  *    
  98.  * ----------------
  99.  */
  100. IndexScanDesc
  101. RelationGetIndexScan(relation, scanFromEnd, numberOfKeys, key)
  102.     Relation    relation;
  103.     Boolean    scanFromEnd;
  104.     uint16    numberOfKeys;
  105.     ScanKey    key;
  106. {
  107.     IndexScanDesc    scan;
  108.  
  109.     if (! RelationIsValid(relation))
  110.     elog(WARN, "RelationGetIndexScan: relation invalid");
  111.  
  112.     scan = (IndexScanDesc)
  113.     palloc(sizeof *scan + (numberOfKeys - 1) * sizeof key->data[0]);
  114.  
  115.     scan->relation = relation;
  116.     scan->opaque = (Pointer) NULL;
  117.     scan->numberOfKeys = numberOfKeys;
  118.  
  119.     ItemPointerSetInvalid(&scan->previousItemData);
  120.     ItemPointerSetInvalid(&scan->currentItemData);
  121.     ItemPointerSetInvalid(&scan->nextItemData);
  122.     ItemPointerSetInvalid(&scan->previousMarkData);
  123.     ItemPointerSetInvalid(&scan->currentMarkData);
  124.     ItemPointerSetInvalid(&scan->nextMarkData);
  125.  
  126.     index_rescan(scan, scanFromEnd, key);
  127.  
  128.     return (scan);
  129. }
  130.  
  131. /* ----------------
  132.  *  IndexScanRestart -- Restart an index scan.
  133.  *
  134.  *    This routine isn't used by any existing access method.  It's
  135.  *    appropriate if relation level locks are what you want.
  136.  *
  137.  *  Returns:
  138.  *    None.
  139.  *
  140.  *  Side Effects:
  141.  *    None.
  142.  * ----------------
  143.  */
  144.  
  145. void
  146. IndexScanRestart(scan, scanFromEnd, key)
  147.     IndexScanDesc    scan;
  148.     bool        scanFromEnd;
  149.     ScanKey        key;
  150. {
  151.     if (! IndexScanIsValid(scan))
  152.     elog(WARN, "IndexScanRestart: invalid scan");
  153.  
  154.     ItemPointerSetInvalid(&scan->previousItemData);
  155.     ItemPointerSetInvalid(&scan->currentItemData);
  156.     ItemPointerSetInvalid(&scan->nextItemData);
  157.  
  158.     if (RelationGetNumberOfBlocks(scan->relation) == 0) 
  159.     scan->flags = ScanUnmarked;
  160.     else if (scanFromEnd)
  161.     scan->flags = ScanUnmarked | ScanUncheckedPrevious;
  162.     else
  163.     scan->flags = ScanUnmarked | ScanUncheckedNext;
  164.  
  165.     scan->scanFromEnd = (Boolean) scanFromEnd;
  166.  
  167.     if (scan->numberOfKeys > 0)
  168.     bcopy((Pointer)& key->data[0],
  169.           (Pointer)& scan->keyData.data[0],
  170.           scan->numberOfKeys * sizeof key->data[0]);
  171. }
  172.  
  173. /* ----------------
  174.  *  IndexScanEnd -- End and index scan.
  175.  *
  176.  *    This routine is not used by any existing access method, but is
  177.  *    suitable for use if you don't want to do sophisticated locking.
  178.  *
  179.  *  Returns:
  180.  *    None.
  181.  *
  182.  *  Side Effects:
  183.  *    None.
  184.  * ----------------
  185.  */
  186. void
  187. IndexScanEnd(scan)
  188.     IndexScanDesc    scan;
  189. {
  190.     if (! IndexScanIsValid(scan))
  191.     elog(WARN, "IndexScanEnd: invalid scan");
  192.  
  193.     pfree((Pointer) scan);
  194. }
  195.  
  196. /* ----------------
  197.  *  IndexScanMarkPosition -- Mark current position in a scan.
  198.  *
  199.  *    This routine isn't used by any existing access method, but is the
  200.  *    one that AM implementors should use, if they don't want to do any
  201.  *    special locking.  If relation-level locking is sufficient, this is
  202.  *    the routine for you.
  203.  *
  204.  *  Returns:
  205.  *    None.
  206.  *
  207.  *  Side Effects:
  208.  *    None.
  209.  * ----------------
  210.  */
  211. void
  212. IndexScanMarkPosition(scan)
  213.     IndexScanDesc    scan;
  214. {
  215.     RetrieveIndexResult    result;
  216.  
  217.     if (scan->flags & ScanUncheckedPrevious) {
  218.     result = (RetrieveIndexResult)
  219.         index_getnext(scan, BackwardScanDirection);
  220.  
  221.     if (RetrieveIndexResultIsValid(result)) {
  222.         scan->previousItemData =
  223.         *RetrieveIndexResultGetIndexItemPointer(result);
  224.     } else {
  225.         ItemPointerSetInvalid(&scan->previousItemData);
  226.     }
  227.  
  228.     } else if (scan->flags & ScanUncheckedNext) {
  229.     result = (RetrieveIndexResult)
  230.         index_getnext(scan, ForwardScanDirection);
  231.  
  232.     if (RetrieveIndexResultIsValid(result)) {
  233.         scan->nextItemData =
  234.         *RetrieveIndexResultGetIndexItemPointer(result);
  235.     } else {
  236.         ItemPointerSetInvalid(&scan->nextItemData);
  237.     }
  238.     }
  239.  
  240.     scan->previousMarkData = scan->previousItemData;
  241.     scan->currentMarkData = scan->currentItemData;
  242.     scan->nextMarkData = scan->nextItemData;
  243.  
  244.     scan->flags = 0x0;    /* XXX should have a symbolic name */
  245. }
  246.  
  247. /* ----------------
  248.  *  IndexScanRestorePosition -- Restore position on a marked scan.
  249.  *
  250.  *    This routine isn't used by any existing access method, but is the
  251.  *    one that AM implementors should use if they don't want to do any
  252.  *    special locking.  If relation-level locking is sufficient, then
  253.  *    this is the one you want.
  254.  *
  255.  *  Returns:
  256.  *    None.
  257.  *
  258.  *  Side Effects:
  259.  *    None.
  260.  * ----------------
  261.  */
  262. void
  263. IndexScanRestorePosition(scan)
  264.     IndexScanDesc    scan;
  265. {    
  266.     RetrieveIndexResult    result;
  267.  
  268.     if (scan->flags & ScanUnmarked) 
  269.     elog(WARN, "IndexScanRestorePosition: no mark to restore");
  270.  
  271.     scan->previousItemData = scan->previousMarkData;
  272.     scan->currentItemData = scan->currentMarkData;
  273.     scan->nextItemData = scan->nextMarkData;
  274.  
  275.     scan->flags = 0x0;    /* XXX should have a symbolic name */
  276. }
  277.  
  278. /* ----------------
  279.  *  IndexScanGetRetrieveIndexResult 
  280.  *
  281.  *  Return a RetrieveIndexResult for the next tuple in the index scan.
  282.  *  A RetrieveIndexResult (see itup.h) is a index tuple/heap tuple pair.
  283.  *  This routine is used primarily by the vacuum daemon, so that it can
  284.  *  delete index tuples associated with zapped heap tuples.
  285.  *
  286.  *  Parameters:
  287.  *        scan -- Index scan to use.
  288.  *        direction -- Forward, backward, or no movement.
  289.  *
  290.  *  Returns:
  291.  *        RetrieveIndexResult for the tuple in the scan that's next
  292.  *        in the specified direction.
  293.  *
  294.  *  Side Effects: None.
  295.  * ----------------
  296.  */
  297. RetrieveIndexResult
  298. IndexScanGetRetrieveIndexResult(scan, direction)
  299.     IndexScanDesc    scan;
  300.     ScanDirection    direction;
  301. {
  302.     return (RetrieveIndexResult)
  303.     index_getnext(scan, direction);
  304. }
  305.  
  306. /* ----------------
  307.  *    IndexScanGetGeneralRetrieveIndexResult
  308.  *
  309.  *      A GeneralRetrieveIndexResult (see itup.h) is a index tuple
  310.  *    rule lock pair.  But currently we don't support index rule
  311.  *    lock results so this routine is pretty bogus.
  312.  * ----------------
  313.  */
  314. GeneralRetrieveIndexResult
  315. IndexScanGetGeneralRetrieveIndexResult(scan, direction)
  316.     IndexScanDesc    scan;
  317.     ScanDirection    direction;
  318. {
  319.     RetrieveIndexResult        result;
  320.     ItemPointer         heapItemPointer;
  321.     GeneralRetrieveIndexResult    generalResult;
  322.  
  323.     /* ----------------
  324.      *    use index_getnext to get the "RetrieveIndexResult"
  325.      * ----------------
  326.      */
  327.     result = (RetrieveIndexResult) index_getnext(scan, direction);
  328.  
  329.     if (! RetrieveIndexResultIsValid(result))
  330.     return (GeneralRetrieveIndexResult) NULL;
  331.  
  332.     /* ----------------
  333.      *    silly crap to convert a "RetrieveIndexResult" to a
  334.      *  "GeneralRetrieveIndexResult".  
  335.      * ----------------
  336.      */
  337.     heapItemPointer = RetrieveIndexResultGetHeapItemPointer(result);
  338.  
  339.     generalResult = (GeneralRetrieveIndexResult) palloc(sizeof *result);
  340.     generalResult->heapItemData = *heapItemPointer;
  341.  
  342.     pfree(result);
  343.     return generalResult;
  344. }
  345.